#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         MultipleChoiceEditlet.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the MultipleChoiceEditlet class, that is
#               used to generate the Multiple Choice
#               'Answers' property editor.
#
# Note:         Only one of these Editlets should ever be generated
#               per propertyeditor page
#
# See Also:     PropertyEditlet, PropertyRefleciton, 
#               PropertyDefinition, PropertyAccess 
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Editlet import Editlet
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.Editlets.HTML.HTMLEditlet import *
from Products.KnowledgeEngine.Components.MultipleChoice.MultipleChoice import Answer

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
import string


def loadTemplate():    
    """ Reloads the HTML Template from the filesystem """
    
    # Open the file
    filename = os.path.dirname(__file__) + '/MultipleChoiceEditlet.html'
    file = open(filename)
    
    # Read the contents and return
    return "\n".join(file.xreadlines())
        
    


#####################################################################
## MultipleChoiceEditlet Class Definition
class MultipleChoiceEditlet(HTMLEditlet):
    """
        An editlet for editing Numeric properties  
    """
    
    #---------------------------------------------------------------#
    
    def isEditable(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns if the specified propertyDefinition can be
            edited by this editlet
        """

        return propertyDefinition.getType() == "ANSWER_LIST"
        
    #---------------------------------------------------------------#

    def generateEditorFor(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns a HTML editlet for the specified property.
        """

        #the resulting editlet
        result = ""

        #-----------------
        #is the property read only?        
        if propertyDefinition.isReadPermitted() and not propertyDefinition.isWritePermitted():

            #get the value for the property
            if isForConstructor:
                value = propertyDefinition.getDefaultValue()
            else:
                value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            
            #create the editor
            result = "*insert read-only value here*" % (value,)
        
        #-----------------
        #is the property writeable?
        if propertyDefinition.isWritePermitted():
       
            if propertyDefinition.isReadPermitted():
                #get the value for the property
                if isForConstructor:
                    value = propertyDefinition.getDefaultValue()
                else:
                    #get the value for the property
                    value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            else:
                #not readable so the default is ""
                value = ""

            #generate the appropriate epoz editor link
            if context != None and self.isEpozAvailable(context):
                #generate an enabled epoz link
                epozLink = """<a href="javascript:void(0)" onClick="javascript:window.open('%s/epozEditor?propertyIdentity=' + this.previousSibling.id,'epozEditor','width=760,height=580,top=20,left=20,menubar=no,toolbar=no,scrollbars=yes,resizable=yes,status==yes').focus();"><img src="/misc_/KnowledgeEngine/epoz.enabled.icon.gif" border="0" align="top"></a>""" % (context.getAbsolutePath(),)

            else:
                #generate an disabled epoz icon
                epozLink = """<img src="/misc_/KnowledgeEngine/epoz.disabled.icon.gif" border="0" align="top">"""           
                
                
            # If we're running in debug more, reload the template
            if os.environ.get('Z_DEBUG_MODE',0):
                self.editletHTMLTemplate = loadTemplate()                
                
            #create the editor
            result = string.replace(self.editletHTMLTemplate, "EPOZ", epozLink)       
                        
        return result
        
    #---------------------------------------------------------------#

    def generateEditorJSInitialisation(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns Javascript to initialise the current page for this editlet
        """
        
        #the resulting javascript
        javascript = ""
        
        #we use the default answers for a constructor
        if isForConstructor:
            answerList = propertyDefinition.getDefaultValue()
        else:
            answerList = propertyAccess.getAnswerList()
        
        #add each of the answers to the javascript model        
        for answer in answerList:
            if answer.isCorrect():
                isCorrect = "true"
            else:
                isCorrect = "false"
        
            javascript += 'addAnswer("%s", "%s", "%s", "%s", %s, %s);' % (asJavaScript(answer.getAnswerID()), asJavaScript(answer.getContent()), asJavaScript(answer.getAssessmentContent()), asJavaScript(answer.getReportContent()), answer.getScore(), isCorrect)                     
        
        #add the instruction to render the answers
        javascript += "renderAnswers();"
        return javascript
        
    #---------------------------------------------------------------#

    def updatePropertyWith(self, propertyDefinition, propertyAccess, REQUEST=None):
        """
            Attempts to update the specified property on the
            object implementing the PropertyAccess interface with the
            specified HTTP REQUEST.
        """

        #is write permitted on the specified property?
        if propertyDefinition.isWritePermitted():

            #we're going to build a new answerlist
            answerList = []
        
            #get the number of answers from the request
            nrAnswers = int(REQUEST["keAnswerCount"])

            #create Answer instances for each of the answers
            for idx in range(0,nrAnswers):
                
                #get the values for the answer
                answerID = REQUEST["keAnswerID%s" % idx]
                answerContent = REQUEST["keAnswerContent%s" % idx]
                answerAssessmentContent = REQUEST["keAnswerAssessmentContent%s" % idx]
                answerReportContent = REQUEST["keAnswerReportContent%s" % idx]
                answerScore = float(REQUEST["keAnswerScore%s" % idx])            
                
                #this is to work-around the problem where some browsers don't send back the state of unchanged dynamically created radio buttons
                if REQUEST.has_key("radioIsCorrect"):                       
                    isCorrect = int(REQUEST["radioIsCorrect"]) == idx
                else:
                    isCorrect = false
                option = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[idx]
                
                #create the next answer
                answer = Answer(answerID, answerContent, answerAssessmentContent, answerReportContent, answerScore, isCorrect, option)
                
                #add the answer to the list
                answerList.append(answer)
            
            #ensure one of the answers is correct!
            if len([answer for answer in answerList if answer.isCorrect()]) == 0:
                #attempt to use the previous correct answer (if there is one)
                originalAnswerList = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
                originalCorrectAnswer = [answer for answer in originalAnswerList if answer.isCorrect()]
                if len(originalCorrectAnswer) == 0:
                    originalCorrectAnswer = None
                    answerList[0].setIsCorrect(true)
                else:
                    #get the desired correct answer    
                    originalCorrectAnswer = originalCorrectAnswer[0]
                
                    #search the new answers for the original correct answer and set it when found
                    isFound = false
                    for answer in answerList:
                        if not isFound and answer.getAnswerID() == originalCorrectAnswer.getAnswerID():
                            answer.setIsCorrect(true)
                            isFound = true
                
                    #not found?  so set the first answer as the correct one
                    if not isFound:
                        answerList[0].setIsCorrect(true)


            # Check we have a value if it isMandatory
            propertyDefinition.verifyMandatoryValue(answerList)

                      
            #set the value for the property from the REQUEST
            propertyAccess.setPropertyValue(propertyDefinition.getIdentity(), answerList)
                    
    #---------------------------------------------------------------#

    editletHTMLTemplate = loadTemplate()
    
    
    
    
    
    
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Editlet Information with the Knowledge Engine
registerEditlet("MultipleChoiceEditlet", MultipleChoiceEditlet())

#####################################################################
